package com.core.cloudbusiness.system.trace.service.impl;

import com.core.cloudbusiness.system.trace.service.TraceQueryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author =====Lqj=====
 * @className TraceQueryServiceImpl
 * @description 链路追踪查询服务实现
 * @create 2024/12/17 10:30
 **/
@Slf4j
@Service
public class TraceQueryServiceImpl implements TraceQueryService {

    // 日志文件路径（可配置）
    private static final String LOG_FILE_PATH = "logs/application.log";
    
    // 链路ID正则表达式
    private static final Pattern TRACE_ID_PATTERN = Pattern.compile("\\[TraceId:([a-f0-9]{32})\\]");
    
    // 日志级别正则表达式
    private static final Pattern LOG_LEVEL_PATTERN = Pattern.compile("(DEBUG|INFO|WARN|ERROR)");
    
    // 时间戳正则表达式
    private static final Pattern TIMESTAMP_PATTERN = Pattern.compile("(\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}\\.\\d{3})");

    @Override
    public List<Map<String, Object>> queryLogsByTraceId(String traceId) {
        List<Map<String, Object>> logs = new ArrayList<>();
        
        try {
            File logFile = new File(LOG_FILE_PATH);
            if (!logFile.exists()) {
                log.warn("日志文件不存在: {}", LOG_FILE_PATH);
                return logs;
            }

            try (BufferedReader reader = new BufferedReader(new FileReader(logFile))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    if (line.contains("[TraceId:" + traceId + "]")) {
                        Map<String, Object> logEntry = parseLogLine(line);
                        if (logEntry != null) {
                            logs.add(logEntry);
                        }
                    }
                }
            }
        } catch (IOException e) {
            log.error("读取日志文件失败: {}", e.getMessage(), e);
        }

        // 按时间排序
        logs.sort((a, b) -> {
            String timeA = (String) a.get("timestamp");
            String timeB = (String) b.get("timestamp");
            return timeA.compareTo(timeB);
        });

        return logs;
    }

    @Override
    public Map<String, Object> queryTraceInfo(String traceId) {
        List<Map<String, Object>> logs = queryLogsByTraceId(traceId);
        
        if (logs.isEmpty()) {
            return null;
        }

        Map<String, Object> traceInfo = new HashMap<>();
        traceInfo.put("traceId", traceId);
        traceInfo.put("totalLogs", logs.size());

        // 提取基本信息
        Map<String, Object> firstLog = logs.get(0);
        Map<String, Object> lastLog = logs.get(logs.size() - 1);

        traceInfo.put("startTime", firstLog.get("timestamp"));
        traceInfo.put("endTime", lastLog.get("timestamp"));

        // 计算总耗时
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
            Date startTime = sdf.parse((String) firstLog.get("timestamp"));
            Date endTime = sdf.parse((String) lastLog.get("timestamp"));
            long duration = endTime.getTime() - startTime.getTime();
            traceInfo.put("duration", duration);
        } catch (Exception e) {
            log.warn("计算耗时失败: {}", e.getMessage());
            traceInfo.put("duration", 0);
        }

        // 提取用户信息和请求信息
        for (Map<String, Object> logEntry : logs) {
            String message = (String) logEntry.get("message");
            if (message.contains("初始化链路追踪")) {
                extractTraceInitInfo(message, traceInfo);
                break;
            }
        }

        // 统计日志级别
        Map<String, Long> levelStats = logs.stream()
                .collect(Collectors.groupingBy(
                        log -> (String) log.get("level"),
                        Collectors.counting()
                ));
        traceInfo.put("levelStats", levelStats);

        return traceInfo;
    }

    @Override
    public List<Map<String, Object>> queryBusinessOperations(String traceId) {
        return queryLogsByTraceId(traceId).stream()
                .filter(log -> {
                    String message = (String) log.get("message");
                    return message.contains("[Business]") || 
                           message.contains("[Business-Start]") || 
                           message.contains("[Business-End]");
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<Map<String, Object>> queryDatabaseOperations(String traceId) {
        return queryLogsByTraceId(traceId).stream()
                .filter(log -> {
                    String message = (String) log.get("message");
                    return message.contains("[Database]");
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<Map<String, Object>> queryExternalCalls(String traceId) {
        return queryLogsByTraceId(traceId).stream()
                .filter(log -> {
                    String message = (String) log.get("message");
                    return message.contains("[External]");
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<Map<String, Object>> queryCacheOperations(String traceId) {
        return queryLogsByTraceId(traceId).stream()
                .filter(log -> {
                    String message = (String) log.get("message");
                    return message.contains("[Cache]");
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<Map<String, Object>> queryPerformanceRecords(String traceId) {
        return queryLogsByTraceId(traceId).stream()
                .filter(log -> {
                    String message = (String) log.get("message");
                    return message.contains("[Performance]") || 
                           message.contains("[Performance-Slow]");
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<Map<String, Object>> querySecurityEvents(String traceId) {
        return queryLogsByTraceId(traceId).stream()
                .filter(log -> {
                    String message = (String) log.get("message");
                    return message.contains("[Security]");
                })
                .collect(Collectors.toList());
    }

    @Override
    public Map<String, Object> queryFullTraceReport(String traceId) {
        Map<String, Object> report = new HashMap<>();
        
        // 基本信息
        Map<String, Object> traceInfo = queryTraceInfo(traceId);
        if (traceInfo == null) {
            return null;
        }
        report.put("traceInfo", traceInfo);

        // 所有日志
        List<Map<String, Object>> allLogs = queryLogsByTraceId(traceId);
        report.put("allLogs", allLogs);

        // 分类日志
        report.put("businessOperations", queryBusinessOperations(traceId));
        report.put("databaseOperations", queryDatabaseOperations(traceId));
        report.put("externalCalls", queryExternalCalls(traceId));
        report.put("cacheOperations", queryCacheOperations(traceId));
        report.put("performanceRecords", queryPerformanceRecords(traceId));
        report.put("securityEvents", querySecurityEvents(traceId));

        // 统计信息
        Map<String, Object> statistics = new HashMap<>();
        statistics.put("totalLogs", allLogs.size());
        statistics.put("businessOperationCount", ((List<?>) report.get("businessOperations")).size());
        statistics.put("databaseOperationCount", ((List<?>) report.get("databaseOperations")).size());
        statistics.put("externalCallCount", ((List<?>) report.get("externalCalls")).size());
        statistics.put("cacheOperationCount", ((List<?>) report.get("cacheOperations")).size());
        statistics.put("performanceRecordCount", ((List<?>) report.get("performanceRecords")).size());
        statistics.put("securityEventCount", ((List<?>) report.get("securityEvents")).size());
        
        report.put("statistics", statistics);

        return report;
    }

    @Override
    public List<String> queryTraceIdsByUser(Long userId, Long startTime, Long endTime) {
        // 这里可以从数据库查询，简化实现从日志文件查询
        Set<String> traceIds = new HashSet<>();
        
        try {
            File logFile = new File(LOG_FILE_PATH);
            if (!logFile.exists()) {
                return new ArrayList<>();
            }

            try (BufferedReader reader = new BufferedReader(new FileReader(logFile))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    if (line.contains("UserId: " + userId)) {
                        Matcher matcher = TRACE_ID_PATTERN.matcher(line);
                        if (matcher.find()) {
                            traceIds.add(matcher.group(1));
                        }
                    }
                }
            }
        } catch (IOException e) {
            log.error("查询用户链路ID失败: {}", e.getMessage(), e);
        }

        return new ArrayList<>(traceIds);
    }

    @Override
    public List<String> queryTraceIdsByUri(String requestUri, Long startTime, Long endTime) {
        Set<String> traceIds = new HashSet<>();
        
        try {
            File logFile = new File(LOG_FILE_PATH);
            if (!logFile.exists()) {
                return new ArrayList<>();
            }

            try (BufferedReader reader = new BufferedReader(new FileReader(logFile))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    if (line.contains("URI: " + requestUri)) {
                        Matcher matcher = TRACE_ID_PATTERN.matcher(line);
                        if (matcher.find()) {
                            traceIds.add(matcher.group(1));
                        }
                    }
                }
            }
        } catch (IOException e) {
            log.error("查询URI链路ID失败: {}", e.getMessage(), e);
        }

        return new ArrayList<>(traceIds);
    }

    @Override
    public List<String> querySlowTraceIds(Long threshold, Long startTime, Long endTime) {
        Set<String> traceIds = new HashSet<>();
        
        try {
            File logFile = new File(LOG_FILE_PATH);
            if (!logFile.exists()) {
                return new ArrayList<>();
            }

            try (BufferedReader reader = new BufferedReader(new FileReader(logFile))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    if (line.contains("耗时: ") && line.contains("ms")) {
                        // 提取耗时
                        Pattern pattern = Pattern.compile("耗时: (\\d+)ms");
                        Matcher matcher = pattern.matcher(line);
                        if (matcher.find()) {
                            long elapsedTime = Long.parseLong(matcher.group(1));
                            if (elapsedTime > threshold) {
                                Matcher traceIdMatcher = TRACE_ID_PATTERN.matcher(line);
                                if (traceIdMatcher.find()) {
                                    traceIds.add(traceIdMatcher.group(1));
                                }
                            }
                        }
                    }
                }
            }
        } catch (IOException e) {
            log.error("查询慢请求链路ID失败: {}", e.getMessage(), e);
        }

        return new ArrayList<>(traceIds);
    }

    /**
     * 解析日志行
     */
    private Map<String, Object> parseLogLine(String line) {
        Map<String, Object> logEntry = new HashMap<>();
        
        // 提取时间戳
        Matcher timestampMatcher = TIMESTAMP_PATTERN.matcher(line);
        if (timestampMatcher.find()) {
            logEntry.put("timestamp", timestampMatcher.group(1));
        }

        // 提取日志级别
        Matcher levelMatcher = LOG_LEVEL_PATTERN.matcher(line);
        if (levelMatcher.find()) {
            logEntry.put("level", levelMatcher.group(1));
        }

        // 提取链路ID
        Matcher traceIdMatcher = TRACE_ID_PATTERN.matcher(line);
        if (traceIdMatcher.find()) {
            logEntry.put("traceId", traceIdMatcher.group(1));
        }

        // 提取消息内容
        int traceIdEnd = line.indexOf("]", line.indexOf("[TraceId:"));
        if (traceIdEnd > 0 && traceIdEnd + 1 < line.length()) {
            logEntry.put("message", line.substring(traceIdEnd + 1).trim());
        } else {
            logEntry.put("message", line);
        }

        logEntry.put("rawLog", line);

        return logEntry;
    }

    /**
     * 提取链路初始化信息
     */
    private void extractTraceInitInfo(String message, Map<String, Object> traceInfo) {
        // 提取用户ID
        Pattern userIdPattern = Pattern.compile("UserId: (\\d+)");
        Matcher userIdMatcher = userIdPattern.matcher(message);
        if (userIdMatcher.find()) {
            traceInfo.put("userId", Long.parseLong(userIdMatcher.group(1)));
        }

        // 提取用户名
        Pattern userNamePattern = Pattern.compile("UserName: ([^,]+)");
        Matcher userNameMatcher = userNamePattern.matcher(message);
        if (userNameMatcher.find()) {
            traceInfo.put("userName", userNameMatcher.group(1));
        }

        // 提取URI
        Pattern uriPattern = Pattern.compile("URI: ([^,]+)");
        Matcher uriMatcher = uriPattern.matcher(message);
        if (uriMatcher.find()) {
            traceInfo.put("requestUri", uriMatcher.group(1));
        }

        // 提取IP
        Pattern ipPattern = Pattern.compile("IP: ([^,\\s]+)");
        Matcher ipMatcher = ipPattern.matcher(message);
        if (ipMatcher.find()) {
            traceInfo.put("clientIp", ipMatcher.group(1));
        }
    }
}
